(device, start, end, mode) quads which say what it has access to,
and we fake the logical view on top of that. */
struct physdisk_ace {
- struct list_head list;
+ struct list_head list;
- unsigned short device;
- unsigned short partition;
- unsigned long start_sect;
- unsigned long n_sectors;
- int mode;
+ unsigned short device;
+ unsigned short partition;
+ unsigned long start_sect;
+ unsigned long n_sectors;
+ int mode;
};
/* Operation is a blkdev constant i.e. READ, WRITE, ... */
/* Must be called with p->physdev_lock held. */
static struct physdisk_ace *find_ace(const struct task_struct *p,
unsigned short dev,
- unsigned long sect,
- int operation)
+ unsigned long sect, int operation)
{
- struct list_head *cur_ace_head;
- struct physdisk_ace *cur_ace;
-
- list_for_each(cur_ace_head, &p->physdisk_aces) {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
- list);
- DPRINTK("Is [%lx, %lx) good for %lx?\n",
- cur_ace->start_sect, cur_ace->start_sect + cur_ace->n_sectors,
- sect);
- if (sect >= cur_ace->start_sect &&
- sect < cur_ace->start_sect + cur_ace->n_sectors &&
- dev == cur_ace->device &&
- ((operation == READ && (cur_ace->mode & PHYSDISK_MODE_R)) ||
- (operation == WRITE && (cur_ace->mode & PHYSDISK_MODE_W)))) {
- DPRINTK("Yes.\n");
- return cur_ace;
- } else {
- DPRINTK("No.\n");
+ struct list_head *cur_ace_head;
+ struct physdisk_ace *cur_ace;
+
+ list_for_each(cur_ace_head, &p->physdisk_aces) {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ DPRINTK("Is [%lx, %lx) good for %lx?\n",
+ cur_ace->start_sect,
+ cur_ace->start_sect + cur_ace->n_sectors, sect);
+ if (sect >= cur_ace->start_sect
+ && sect < cur_ace->start_sect + cur_ace->n_sectors
+ && dev == cur_ace->device
+ && ((operation == READ && (cur_ace->mode & PHYSDISK_MODE_R))
+ || (operation == WRITE
+ && (cur_ace->mode & PHYSDISK_MODE_W)))) {
+ DPRINTK("Yes.\n");
+ return cur_ace;
+ } else {
+ DPRINTK("No.\n");
+ }
}
- }
- return NULL;
+ return NULL;
}
/* Hold the lock on entry, it remains held on exit. */
unsigned long n_sectors,
struct task_struct *p)
{
- /* Find every ace which intersects [start_sect, start_sect +
- n_sectors] and either remove it completely or truncate it
- down. */
- struct list_head *cur_ace_head;
- struct physdisk_ace *cur_ace, *new_ace;
- unsigned long kill_zone_end, ace_end;
-
- kill_zone_end = start_sect + n_sectors;
- list_for_each(cur_ace_head, &p->physdisk_aces) {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
- list);
- ace_end = cur_ace->start_sect + cur_ace->n_sectors;
- if (cur_ace->start_sect >= kill_zone_end ||
- ace_end <= start_sect ||
- cur_ace->device != dev)
- continue;
-
- DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
- cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
-
- if (cur_ace->start_sect >= start_sect &&
- ace_end <= kill_zone_end) {
- /* ace entirely within kill zone -> kill it */
- list_del(cur_ace_head);
- cur_ace_head = cur_ace_head->prev;
- kfree(cur_ace);
- } else if (ace_end <= kill_zone_end) {
- /* ace start before kill start, ace end in kill zone,
- move ace end. */
- cur_ace->n_sectors = start_sect - cur_ace->start_sect;
- } else if (cur_ace->start_sect >= start_sect) {
- /* ace start after kill start, ace end outside kill zone,
- move ace start. */
- cur_ace->start_sect = kill_zone_end;
- cur_ace->n_sectors = ace_end - cur_ace->start_sect;
- } else {
- /* The fun one: the ace entirely includes the kill zone. */
- /* Cut the current ace down to just the bit before the kzone,
- create a new ace for the bit just after it. */
- new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
- new_ace->device = dev;
- new_ace->start_sect = kill_zone_end;
- new_ace->n_sectors = ace_end - kill_zone_end;
- new_ace->mode = cur_ace->mode;
-
- cur_ace->n_sectors = start_sect - cur_ace->start_sect;
-
- list_add(&new_ace->list, cur_ace_head);
+ /* Find every ace which intersects [start_sect, start_sect +
+ n_sectors] and either remove it completely or truncate it
+ down. */
+ struct list_head *cur_ace_head;
+ struct physdisk_ace *cur_ace, *new_ace;
+ unsigned long kill_zone_end, ace_end;
+
+ kill_zone_end = start_sect + n_sectors;
+ list_for_each(cur_ace_head, &p->physdisk_aces) {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ ace_end = cur_ace->start_sect + cur_ace->n_sectors;
+ if (cur_ace->start_sect >= kill_zone_end ||
+ ace_end <= start_sect || cur_ace->device != dev)
+ continue;
+
+ DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
+ cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
+
+ if (cur_ace->start_sect >= start_sect && ace_end <= kill_zone_end) {
+ /* ace entirely within kill zone -> kill it */
+ list_del(cur_ace_head);
+ cur_ace_head = cur_ace_head->prev;
+ kfree(cur_ace);
+ } else if (ace_end <= kill_zone_end) {
+ /* ace start before kill start, ace end in kill zone,
+ move ace end. */
+ cur_ace->n_sectors = start_sect - cur_ace->start_sect;
+ } else if (cur_ace->start_sect >= start_sect) {
+ /* ace start after kill start, ace end outside kill zone,
+ move ace start. */
+ cur_ace->start_sect = kill_zone_end;
+ cur_ace->n_sectors = ace_end - cur_ace->start_sect;
+ } else {
+ /* The fun one: the ace entirely includes the kill zone. */
+ /* Cut the current ace down to just the bit before the kzone,
+ create a new ace for the bit just after it. */
+ new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
+ new_ace->device = dev;
+ new_ace->start_sect = kill_zone_end;
+ new_ace->n_sectors = ace_end - kill_zone_end;
+ new_ace->mode = cur_ace->mode;
+
+ cur_ace->n_sectors = start_sect - cur_ace->start_sect;
+
+ list_add(&new_ace->list, cur_ace_head);
+ }
}
- }
}
/* Hold the lock on entry, it remains held on exit. */
unsigned short partition,
unsigned long start_sect,
unsigned long n_sectors,
- int mode,
- struct task_struct *p)
+ int mode, struct task_struct *p)
{
- struct physdisk_ace *cur_ace;
-
- /* Make sure it won't overlap with any existing ACEs. */
- /* XXX this isn't quite right if the domain already has read access
- and we try to grant write access, or vice versa. */
- xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
-
- if (mode) {
- cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
- cur_ace->device = dev;
- cur_ace->start_sect = start_sect;
- cur_ace->n_sectors = n_sectors;
- cur_ace->mode = mode;
- cur_ace->partition = partition;
-
- list_add_tail(&cur_ace->list, &p->physdisk_aces);
- }
-
- return 0;
+ struct physdisk_ace *cur_ace;
+
+ /* Make sure it won't overlap with any existing ACEs. */
+ /* XXX this isn't quite right if the domain already has read access
+ and we try to grant write access, or vice versa. */
+ xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
+
+ if (mode) {
+ cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
+ cur_ace->device = dev;
+ cur_ace->start_sect = start_sect;
+ cur_ace->n_sectors = n_sectors;
+ cur_ace->mode = mode;
+ cur_ace->partition = partition;
+
+ list_add_tail(&cur_ace->list, &p->physdisk_aces);
+ }
+
+ return 0;
}
-static void xen_physdisk_probe_access(physdisk_probebuf_t *buf,
+static void xen_physdisk_probe_access(physdisk_probebuf_t * buf,
struct task_struct *p)
{
- int max_aces;
- int n_aces;
- struct list_head *cur_ace_head;
- struct physdisk_ace *cur_ace;
- int x = 0;
-
- max_aces = buf->n_aces;
- n_aces = 0;
- list_for_each(cur_ace_head, &p->physdisk_aces) {
- x++;
- if (x >= buf->start_ind) {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
- list);
- buf->entries[n_aces].device = cur_ace->device;
- buf->entries[n_aces].partition = cur_ace->partition;
- buf->entries[n_aces].start_sect = cur_ace->start_sect;
- buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
- buf->entries[n_aces].mode = cur_ace->mode;
- n_aces++;
- if (n_aces >= max_aces)
- break;
+ int max_aces;
+ int n_aces;
+ struct list_head *cur_ace_head;
+ struct physdisk_ace *cur_ace;
+ int x = 0;
+
+ max_aces = buf->n_aces;
+ n_aces = 0;
+ list_for_each(cur_ace_head, &p->physdisk_aces) {
+ x++;
+ if (x >= buf->start_ind) {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ buf->entries[n_aces].device = cur_ace->device;
+ buf->entries[n_aces].partition = cur_ace->partition;
+ buf->entries[n_aces].start_sect = cur_ace->start_sect;
+ buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
+ buf->entries[n_aces].mode = cur_ace->mode;
+ n_aces++;
+ if (n_aces >= max_aces)
+ break;
+ }
}
- }
- buf->n_aces = n_aces;
+ buf->n_aces = n_aces;
}
-int xen_physdisk_grant(xp_disk_t *xpd_in)
+int xen_physdisk_grant(xp_disk_t * xpd_in)
{
- struct task_struct *p;
- xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
- int res;
-
- p = current;
- DPRINTK("Have current.\n");
- DPRINTK("Target domain %x\n", xpd->domain);
-
- p = find_domain_by_id(xpd->domain);
- if (p == NULL) {
- DPRINTK("Bad domain!\n");
- res = 1;
- goto out;
- }
- spin_lock(&p->physdev_lock);
- res = xen_physdisk_grant_access(xpd->device,
- xpd->partition,
- xpd->start_sect,
- xpd->n_sectors,
- xpd->mode,
- p);
- spin_unlock(&p->physdev_lock);
- put_task_struct(p);
-
- out:
- unmap_domain_mem(xpd);
- return res;
-}
+ struct task_struct *p;
+ xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
+ int res;
+
+ p = current;
+ DPRINTK("Have current.\n");
+ DPRINTK("Target domain %x\n", xpd->domain);
+
+ p = find_domain_by_id(xpd->domain);
+ if (p == NULL) {
+ DPRINTK("Bad domain!\n");
+ res = 1;
+ goto out;
+ }
+ spin_lock(&p->physdev_lock);
+ res = xen_physdisk_grant_access(xpd->device,
+ xpd->partition,
+ xpd->start_sect,
+ xpd->n_sectors, xpd->mode, p);
+ spin_unlock(&p->physdev_lock);
+ put_task_struct(p);
-int xen_physdisk_probe(struct task_struct *requesting_domain,
- physdisk_probebuf_t *buf_in)
-{
- struct task_struct *p;
- physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in));
- int res;
-
- if (requesting_domain->domain != 0 &&
- requesting_domain->domain != buf->domain) {
- res = 1;
- goto out;
- }
-
- p = find_domain_by_id(buf->domain);
- if (p == NULL) {
- res = 1;
- goto out;
- }
-
- spin_lock(&p->physdev_lock);
- xen_physdisk_probe_access(buf, p);
- spin_unlock(&p->physdev_lock);
- put_task_struct(p);
-
- res = 0;
- out:
- unmap_domain_mem(buf);
- return res;
+ out:
+ unmap_domain_mem(xpd);
+ return res;
}
-int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p,
- int operation)
+int xen_physdisk_probe(struct task_struct *requesting_domain,
+ physdisk_probebuf_t * buf_in)
{
- struct physdisk_ace *cur_ace;
- unsigned long sect;
+ struct task_struct *p;
+ physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in));
+ int res;
+
+ if (requesting_domain->domain != 0 &&
+ requesting_domain->domain != buf->domain) {
+ res = 1;
+ goto out;
+ }
- DPRINTK("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n",
- p->domain, pseg->sector_number, pseg->nr_sects);
+ p = find_domain_by_id(buf->domain);
+ if (p == NULL) {
+ res = 1;
+ goto out;
+ }
- for (sect = pseg->sector_number;
- sect < pseg->sector_number + pseg->nr_sects;
- ) {
- /* XXX this would be a lot faster if the aces were sorted on start
- address. Also in revoke_access. */
spin_lock(&p->physdev_lock);
- cur_ace = find_ace(p, pseg->dev, sect, operation);
+ xen_physdisk_probe_access(buf, p);
spin_unlock(&p->physdev_lock);
- if (!cur_ace) {
- /* Default closed. */
- return 0;
+ put_task_struct(p);
+
+ res = 0;
+ out:
+ unmap_domain_mem(buf);
+ return res;
+}
+
+int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p,
+ int operation)
+{
+ struct physdisk_ace *cur_ace;
+ unsigned long sect;
+
+ DPRINTK
+ ("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n",
+ p->domain, pseg->sector_number, pseg->nr_sects);
+
+ for (sect = pseg->sector_number;
+ sect < pseg->sector_number + pseg->nr_sects;) {
+ /* XXX this would be a lot faster if the aces were sorted on start
+ address. Also in revoke_access. */
+ spin_lock(&p->physdev_lock);
+ cur_ace = find_ace(p, pseg->dev, sect, operation);
+ spin_unlock(&p->physdev_lock);
+ if (!cur_ace) {
+ /* Default closed. */
+ return 0;
+ }
+ sect +=
+ MAX(cur_ace->n_sectors,
+ pseg->nr_sects + pseg->sector_number - sect);
}
- sect += MAX(cur_ace->n_sectors, pseg->nr_sects + pseg->sector_number - sect);
- }
- return 1;
+ return 1;
}
void destroy_physdisk_aces(struct task_struct *p)
{
- struct list_head *cur_ace_head, *next_head;
- struct physdisk_ace *cur_ace;
-
- spin_lock(&p->physdev_lock); /* We never release this again. */
-
- for (cur_ace_head = p->physdisk_aces.next;
- cur_ace_head != &p->physdisk_aces;
- cur_ace_head = next_head) {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
- list);
- next_head = cur_ace_head->next;
- kfree(cur_ace);
- }
+ struct list_head *cur_ace_head, *next_head;
+ struct physdisk_ace *cur_ace;
+
+ spin_lock(&p->physdev_lock); /* We never release this again. */
+
+ for (cur_ace_head = p->physdisk_aces.next;
+ cur_ace_head != &p->physdisk_aces; cur_ace_head = next_head) {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ next_head = cur_ace_head->next;
+ kfree(cur_ace);
+ }
}